package org.restql.webapp;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.prefs.Preferences;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.restql.db.operation.DatabaseDelete;
import org.restql.db.operation.DatabaseDtd;
import org.restql.db.operation.DatabaseGet;
import org.restql.db.operation.DatabaseInsert;
import org.restql.db.operation.DatabaseSelect;
import org.restql.db.operation.DatabaseUpdate;
import org.restql.db.resource.DatabaseResource;
import org.restql.db.resource.ModifiableDatabaseResource;
import org.restql.db.resource.ModifiableDatabaseResourceImpl;
import org.restql.db.resource.RequestResource;
import org.springframework.beans.factory.xml.XmlBeanFactory;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.FileSystemResource;

public class RestQLServlet extends HttpServlet {

	static final long serialVersionUID = 1L;
	static Log logger = LogFactory.getLog(RestQLServlet.class);
	Preferences userPrefs;
	RestQLResourceContainer resourceContainer = null;
	static List<RestQLServlet> allServletInstance = new ArrayList<RestQLServlet>();
	String configFilePath = null;

	public void init(ServletConfig servletConfig) {
		logger.info("Calling init");
		ServletConfig sc = servletConfig;
	    /*
	    this.jdbcUrl = sc.getInitParameter("jdbcUrl");
	    this.jdbcDriver = sc.getInitParameter("jdbcDriver");
	    this.username = sc.getInitParameter("username");
	    this.password = sc.getInitParameter("password");
	     */
		userPrefs = Preferences.userNodeForPackage(RestQLService.class);
		allServletInstance.add(this);
		applyConfig();
	}

	public static void applyConfigToAll() {
		logger.info("Reapplying configuration.");
		for (RestQLServlet rqls : allServletInstance) {
			rqls.applyConfig();
		}
	}

	protected void applyConfig() {
		String configType = userPrefs.get("configType", "auto");
		try {
			AbstractResource res = null;
			
			if (configFilePath != null) {
				logger.info("Using config file specified at launch: " + configFilePath);
				res = new FileSystemResource(configFilePath);
			} else if (configType.equals("auto")) {
				logger.info("Using auto config.");
				res = new ClassPathResource("restqlResources.xml");
			} else if (configType.equals("file")){
				logger.info("Using file config.");
				String configLocation = userPrefs.get("configLocation", "");
				res = new FileSystemResource(configLocation);
			}

			XmlBeanFactory factory = new XmlBeanFactory(res);
			this.resourceContainer = (RestQLResourceContainer) factory.getBean("restQLResourceContainer");
			
			// Auto configure the config based on User preferences
			if (configType.equals("auto")) {
				ModifiableDatabaseResourceImpl dbResource = 
					(ModifiableDatabaseResourceImpl) this.resourceContainer.getResources().get(0);
				if (userPrefs.get("allowGet", "true").equals("false")) {
					dbResource.setAllowSelect(false);
				}
				if (userPrefs.get("allowPut", "true").equals("false")) {
					dbResource.setAllowInsert(false);
				}
				if (userPrefs.get("allowPost", "true").equals("false")) {
					dbResource.setAllowUpdate(false);
				}
				if (userPrefs.get("allowDelete", "true").equals("false")) {
					dbResource.setAllowDelete(false);
				}
			}
			
		} catch (Exception e) {
			logger.error(e);
		}
	}

	public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		new RestQLService(this).doGet(request, response);		
	}

	public void doPut(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		new RestQLService(this).doPut(request, response);		
	}
	
	public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		new RestQLService(this).doPost(request, response);		
	}

	public void doDelete(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
		new RestQLService(this).doDelete(request, response);		
	}

}